package com.slicktechnologies.shared.common.businessprocesslayer;

import static com.googlecode.objectify.ObjectifyService.ofy;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Vector;

import com.google.gwt.core.shared.GwtIncompatible;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.annotation.Cache;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Ignore;
import com.googlecode.objectify.annotation.Index;
import com.googlecode.objectify.annotation.OnLoad;
import com.googlecode.objectify.annotation.OnSave;
import com.simplesoftwares.client.library.helperconstants.ColumnDatatype;
import com.simplesoftwares.client.library.helperconstants.FormTypes;
import com.simplesoftwares.rebind.annatonations.SearchAnnotation;
import com.simplesoftwares.rebind.annatonations.SearchCompositeAnnatonation;
import com.simplesoftwares.rebind.annatonations.TableAnnotation;
import com.slicktechnologies.client.config.configurations.ConfigTypes;
import com.slicktechnologies.server.GenricServiceImpl;
import com.slicktechnologies.shared.Contract;
import com.slicktechnologies.shared.MyUtility;
import com.slicktechnologies.shared.Quotation;
import com.slicktechnologies.shared.common.helperlayer.Address;
import com.slicktechnologies.shared.common.helperlayer.Config;
import com.slicktechnologies.shared.common.helperlayer.Contact;
import com.slicktechnologies.shared.common.helperlayer.TaxInfo;
import com.slicktechnologies.shared.common.personlayer.Person;
import com.slicktechnologies.shared.common.relationalLayer.CustomerRelation;

/**
 * Represents a person which is potential or existing or past Customer.
 * Without Customer No {@link Contract}
 * {@link Quotation}  or {@link Service} or {@link Lead} can be created.(without customer no 
 * business process can be created)
 */
@Entity
@Cache
@SearchCompositeAnnatonation(Datatype = { ColumnDatatype.PERSONINFO }, flexFormNumber = {"20" }, 
title = { "" }, variableName = { "personInfo" },rowspan={1},colspan={5},extra={"Customer"})
public class Customer extends Person implements BusinessProcess
{
	
	public final static String  CUSTOMERCREATED="Created";
	public final static String  CUSTOMERPROSPECT="Prospect";
	public final static String  CUSTOMERACTIVE="Active";
	
	/***********************************************Entity Attributes*****************************/
	/** The Constant serialVersionUID. */
	
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 8399036173715271427L;

	/** The taxinfo for this Customer */
	protected TaxInfo taxInfo;
	
	/** Business process for this Customer*/
	protected ConcreteBusinessProcess businessProcess;
	
	
	/** Level of Customer **/
	@Index
	protected String customerLevel;
	/**Priority of Customer **/
	@Index 
	protected String customerPriority;
	
	/**If true it will represent that the customer is a company else an individual*/
	protected boolean isCompany;
	
	
	/**
	 * Company Name attribute , this attribute can change in future
	 */
	@Index
	protected String companyName;
	/***********************************************Relational Attributes*****************************/
	protected Key<Config> customerPriorityKey;
	
	protected Key<Config> customerLevelKey;

	
	/***********************************************One Kind Attribute*****************************************************/
	@Index
	protected Key<CustomerRelation> keyName;
	@Ignore
	protected boolean nameChanged=false;
	@Ignore
	protected boolean cellNo1Changed=false;
	
	/** Instantiates a new customer*/
	public Customer() 
	{
		super();
		
		taxInfo=new TaxInfo();
		businessProcess=new ConcreteBusinessProcess();
		
		customerLevel="";
		customerPriority="";
	
		nameChanged=false;
		cellNo1Changed=false;
		
		Contact contact=new Contact();
		this.contacts=new Vector<Contact>();
		contacts.add(contact);
		contact=new Contact();
		contacts.add(contact);
		
	}
	
	/**
	 * Gets the taxinfo.
	 *
	 * @return the taxinfo
	 */
	public TaxInfo getTaxInfo() {
		return taxInfo;
	}


	/**
	 * Sets the taxinfo.
	 *
	 * @param taxinfo the new taxinfo
	 */
	public void setTaxInfo(TaxInfo taxinfo) {
		if(taxinfo!=null)
			this.taxInfo = taxinfo;
	}
	
	@Override
	@SearchAnnotation(Datatype = ColumnDatatype.OBJECTLISTBOXBRANCH, flexFormNumber = "11", title = "Branch", variableName = "olbBranch",EmbededQuerry="businessProcess.branch")
	@TableAnnotation(ColType = FormTypes.TEXTCOLUM, colNo = 10, isFieldUpdater = false, isSortable = true, title = "Branch")
	public String getBranch() {
		return businessProcess.getBranch();
	}

	@Override
	@SearchAnnotation(Datatype = ColumnDatatype.OBJECTLISTBOXEMPLOYEE, flexFormNumber = "11", title = "Sales Person", variableName = "olbSalesPerson",EmbededQuerry="businessProcess.employee")
	@TableAnnotation(ColType = FormTypes.TEXTCOLUM, colNo = 3, isFieldUpdater = false, isSortable = true, title = "Sales Person")
	public String getEmployee() {
		return businessProcess.getEmployee();
	}

	@Override
	@SearchAnnotation(Datatype = ColumnDatatype.LISTBOX, flexFormNumber = "01", title = "Status", variableName = "lbStatus",EmbededQuerry="businessProcess.status",extra="getStatusArraylist()",colspan=2)
	@TableAnnotation(ColType = FormTypes.TEXTCOLUM, colNo = 8, isFieldUpdater = false, isSortable = true, title = "Status")
	public String getStatus() {
		return businessProcess.getStatus();
	}
	
	@Override
	@SearchAnnotation(Datatype = ColumnDatatype.DATECOMPARATOR, flexFormNumber = "00", title = "", variableName = "dateComparator",extra="Customer",EmbededQuerry="businessProcess.creationDate")
	@TableAnnotation(ColType = FormTypes.DATETEXTCELL, colNo = 3, isFieldUpdater = false, isSortable = true, title = "Reg. Date")
	public Date getCreationDate() {

		return businessProcess.getCreationDate();
	}
	
	

	
	@Override
	public String getApproverName() {
		return businessProcess.getApproverName();
	}

	@Override
	public Date getApprovalDate() {
		// TODO Auto-generated method stub
		return businessProcess.getApprovalDate();
	}

	@Override
	public void setBranch(String branch) {
		if(branch!=null)
		  businessProcess.setBranch(branch.trim());
		
	}

	@Override
	public void setEmployee(String employee) {
		if(employee!=null)
		  businessProcess.setEmployee(employee.trim());
		
	}

	@Override
	public void setStatus(String status) {
		if(status!=null)
			  businessProcess.setStatus(status.trim());
		
	}
	
	public void setStatusKey(Key<Config>statusKey)
	{
		if(statusKey!=null)
			businessProcess.setStatusKey(statusKey);
	}

	@Override
	public void setCreationDate(Date date) {
		if(date!=null)
			businessProcess.setCreationDate(date);
		
	}



	@Override
	public void setApproverName(String name) {
		if(name!=null)
			businessProcess.setApproverName(name.trim());
		
	}
	
	@Override
	public String getCreationTime() {
		
		return null;
	}

	@Override
	public String getApprovalTime() {
		
		return null;
	}

	@Override
	public void setCreationTime(String time)
	{
		if(time!=null)
			  businessProcess.setCreationTime(time.trim());
		
	}

	@Override
	public void setApprovalTime(String time) 
	{
		if(time!=null)
			  businessProcess.setApprovalTime(time.trim());
		
	}

	@Override
	public void setApprovalDate(Date date) {
		if(date!=null)
			businessProcess.setApprovalDate(date);
		
	}

	
	public ConcreteBusinessProcess getBusinessProcess() {
		return businessProcess;
	}

	public void setBusinessProcess(ConcreteBusinessProcess businessProcess) {
		if(businessProcess!=null)
			this.businessProcess = businessProcess;
	}

	@TableAnnotation(ColType = FormTypes.TEXTCOLUM, colNo = 4, isFieldUpdater = false, isSortable = true, title = "Group")
	
	@Override
	public String getGroup() {
		return businessProcess.getGroup();
	}

	@Override
	@TableAnnotation(ColType = FormTypes.TEXTCOLUM, colNo = 5, isFieldUpdater = false, isSortable = true, title = "Category")
	
	@SearchAnnotation(Datatype = ColumnDatatype.OBJECTLISTBOXCONFIGCATEGORY, flexFormNumber = "03", title = "Customer Category", variableName = "olbConfigCustomerCategory",extra="CUSTOMERCATEGORY",EmbededQuerry="businessProcess.category")
	public String getCategory() {
		return businessProcess.getCategory();
	}
	
	

	public void setGroup(String group) {
		if(group!=null)
		{
		    group=group.trim();
			businessProcess.setGroup(group);
		}
	}

	public void setCategory(String category) {
		if(category!=null)
		{
		    category=category.trim();
			businessProcess.setCategory(category);
		}
	}

	public void setType(String type) {
		businessProcess.setType(type);
	}

	@SearchAnnotation(Datatype = ColumnDatatype.OBJECTLISTBOXCONFIG, flexFormNumber = "12", title = "Level", variableName = "olbConfigCustomerLevel",extra="CUSTOMERLEVEL")
	@TableAnnotation(ColType = FormTypes.TEXTCOLUM, colNo = 7, isFieldUpdater = false, isSortable = true, title = "Level")
	public String getCustomerLevel() {
		
		return customerLevel;
	}

	public void setCustomerLevel(String customerLevel) {
		if(customerLevel!=null)
		  this.customerLevel = customerLevel.trim();
	}

	
	@SearchAnnotation(Datatype = ColumnDatatype.OBJECTLISTBOXCONFIG, flexFormNumber = "13", title = "Customer Priority", variableName = "olbConfigCustomerPriority",extra="CUSTOMERPRIORITY")
	@TableAnnotation(ColType = FormTypes.TEXTCOLUM, colNo = 9, isFieldUpdater = false, isSortable = true, title = "Priority")
	public String getCustomerPriority() {
		return customerPriority;
	}

	public void setCustomerPriority(String customerPriority) {
		if(customerPriority!=null)
		   this.customerPriority = customerPriority.trim();
	}
	
	
	
	public String getName()
	{
		return this.fullname;
	}

	public Long getLandline()
	{
		return this.contacts.get(0).getLandline();
	}

	public void setLanline(Long landline)
	{
		if(landline!=null)
			contacts.get(0).setLandline(landline);
		else
			contacts.get(0).setLandline(0l);
	}


	public void setEmail(String email)
	{
		if(email!=null)
			this.contacts.get(0).setEmail(email.trim());
	}

	public String getEmail()
	{
		return this.contacts.get(0).getEmail();
	}

	public Long getLandLine(Long landlineNo)
	{
		return this.contacts.get(0).getLandline();

	}

	public void setLandLine(Long landline)
	{
		if(landline!=null) 
			this.contacts.get(0).setLandline(landline);
	}

	public void setWebsite(String website)
	{
		if(website!=null)
			this.contacts.get(0).setWebsite(website.trim());
	}

	public String getWebsite()
	{
		return this.contacts.get(0).getWebsite();
	}

	@TableAnnotation(ColType = FormTypes.TEXTCOLUM, colNo = 1, isFieldUpdater = false, isSortable = true, title = "Phone")
	
	public  Long getCellNumber1()
	{
		return contacts.get(0).getCellNo1();
	}

	public  void setCellNumber1(Long cellNuber1)
	{
		if(cellNuber1!=null)  
		{
			
			if(!(cellNuber1==contacts.get(0).getCellNo1()))
			{
				cellNo1Changed=true;
			    contacts.get(0).setCellNo1(cellNuber1);
			}
		}
	}

	public  Long getCellNumber2()
	{
		return contacts.get(0).getCellNo2();
	}

	public  void setCellNumber2(Long cellNuber2)
	{
		if(cellNuber2!=null)  
			contacts.get(0).setCellNo2(cellNuber2);
	}

	public  Long getFaxNumber()
	{
		return contacts.get(0).getFaxNo();
	}

	public  void setFaxNumber(Long faxno)
	{
		if(faxno!=null)    
			contacts.get(0).setFaxNo(faxno);
	}
	
	public void setAdress(Address address)
	{
		if(address!=null)
			this.contacts.get(0).setAddress(address);
	}

	public Address getAdress()
	{
		return contacts.get(0).getAddress();
	}
	
	
	
	public Address getSecondaryAdress()
	{
		return contacts.get(1).getAddress();
	}
	
	public void setSecondaryAdress(Address address)
	{
	 contacts.get(1).setAddress(address);
	}
	
	@Override
	public void setFirstName(String firstName) 
	{
		if(!(this.firstName.equals(getFirstName())))
			nameChanged=true;
		super.setFirstName(firstName);
	}

	@Override
	public void setMiddleName(String middleName)
	{
		if(!(this.middleName.equals(getMiddleName())))
			nameChanged=true;
		super.setMiddleName(middleName);
	}
	
	@Override
	public void setLastName(String lastName) 
	{
		if(!(this.lastName.equals(getLastName())))
			nameChanged=true;
		super.setLastName(lastName);
	}
	@TableAnnotation(ColType = FormTypes.TEXTCOLUM, colNo = 2, isFieldUpdater = false, isSortable = true, title = "Name")
	public String getCompanyName() {
		return companyName;
	}

	public void setCompanyName(String companyName) {
		this.companyName = companyName;
	}

	public Boolean isCompany() {
		return isCompany;
	}

	public void setCompany(Boolean isCompany) {
		this.isCompany = isCompany;
	}
	
	
	public static List<String> getStatusList()
	{
		ArrayList<String> custstatuslist=new ArrayList<String>();
		custstatuslist.add(CUSTOMERACTIVE);
		custstatuslist.add(CUSTOMERCREATED);
		custstatuslist.add(CUSTOMERPROSPECT);
		return custstatuslist;
	}

	@Override
	@SearchAnnotation(Datatype = ColumnDatatype.OBJECTLISTBOXTYPE, flexFormNumber = "02", title = "Customer Type", variableName = "olbConfigCustomerType",extra="CUSTOMERTYPE",EmbededQuerry="businessProcess.type")
	@TableAnnotation(ColType = FormTypes.TEXTCOLUM, colNo =6, isFieldUpdater = false, isSortable = true, title = "Type")
	public String getType() {
		// TODO Auto-generated method stub
		return businessProcess.getType();
	}

	
	
	/**************************************************Relation Managment Part**********************************************/
	@OnSave
	@GwtIncompatible
	public void onSave()
	{
		fillFullName();
		
		businessProcess.OnSave();
		if(isCompany==false)
		  this.companyName=fullname;
		
		
		   
		
		if(id==null)
		{
			
			CustomerRelation personInfo=new CustomerRelation();
			int count=ofy().load().type(Customer.class).count();
			personInfo.setCellNumber(getCellNumber1());
			personInfo.setFullName(getCompanyName());
			personInfo.setCount(count);
			
			keyName=(Key<CustomerRelation>) MyUtility.createRelationalKey(personInfo);
			
		}
		
		else
		{
			if(nameChanged==true || cellNo1Changed==true)
			{
				if(keyName!=null&&nameChanged==true)
				{
				    CustomerRelation customerRelation=new CustomerRelation();
				    customerRelation.setCellNumber(this.getCellNumber1());
				    customerRelation.setFullName(this.getFullname());
					MyUtility.updateRelationalEntity(customerRelation,keyName);
				}
			}
			
			
	
		}
	}
	
	@OnLoad
	@GwtIncompatible
	public void OnLoad()
	{
		fillAllNames();
		businessProcess.OnLoad();

		String priorityName=MyUtility.getConfigNameFromKey(customerPriorityKey);
		if(priorityName!=null)
		{
			if(priorityName.equals("")==false)
				setCustomerPriority(priorityName.trim());
		}
		String typeName=MyUtility.getTypeNameFromKey(businessProcess.getTypeKey());
		if(typeName!=null)
		{
			if(typeName.equals("")==false)
				setType(typeName.trim());
		}
		String levelName=MyUtility.getConfigNameFromKey(customerLevelKey);
		if(levelName!=null)
		{
			if(levelName.equals("")==false)
				setCustomerLevel(levelName.trim());
		}
		
		
		String groupName=MyUtility.getConfigNameFromKey(businessProcess.getGroupKey());
		if(groupName!=null)
		{
			if(groupName.equals("")==false)
				setGroup(groupName.trim());
		}
		String categoryName=MyUtility.getConfigCatNameFromKey(businessProcess.getCategoryKey());
		if(categoryName!=null)
		{
			if(categoryName.equals("")==false)
				setCategory(categoryName.trim());
		}
	}
		
	/**********************************************************************************************************************/

	

	
}
